//
//  SPModelBase.h
//  SPKit
//
//  Created by 李双鹏 on 15/10/04.
//  Copyright (c) 2015年 SP. All rights reserved.
//

#import <Foundation/Foundation.h>

#ifndef __BaseModel_h__
#define __BaseModel_h__

NS_ASSUME_NONNULL_BEGIN

@protocol SPModelBase <NSObject>
@required
/**
 * <Protocol>Create instance from a NSDictionary instance.
 */
+ (instancetype)modelFromDic:(NSDictionary *)dic;

/**
 * <Protocol>Initialize instance from a NSDictionary instance.
 * As a subclass,You must override this method and call initWithDic: for super
 *  to ensure the instance variable _dictionary setted.
 */
- (instancetype)initWithDic:(NSDictionary *)dic;

@optional
/**
 * <Protocol>Create instance from an array which including NSDictionary instances.
 */
+ (NSArray *)modelsFromDicArray:(NSArray *)array;

@property (nonatomic, readonly, retain) NSDictionary *dictionary;
@end


extern NSString const *__savedPath;

@interface SPModelBase : NSObject <SPModelBase> {
@protected
    NSDictionary *_dictionary;
}

/**
 * Create instance from a NSDictionary instance.
 */
+ (instancetype)modelFromDic:(NSDictionary *)dic NS_SWIFT_NAME(init(dic:));

/**
 * Create instances from an array which has included NSDictionary instances.
 */
+ (NSArray *)modelsFromDicArray:(NSArray *)array NS_SWIFT_UNAVAILABLE("In order to eliminated the same method in SPModelBase protocol declaration.");


/**
 * Initialize instance from a NSDictionary instance.
 * As a subclass,You must override this method and call initWithDic: for super
 *  to ensure the instance variable _dictionary setted.
 */
- (instancetype)initWithDic:(NSDictionary *)dic NS_DESIGNATED_INITIALIZER;

/**
 * Contains key-value-pair that's the dictionary for initialized. 
 * And if the value changed after initialized, the value will change for the pair.
 */
@property (nonatomic, readonly, retain) NSDictionary *dictionary;


/**
 * Convert to dictionary.Return an dictionary while this object wasn't created from Dictionary.
 * Or you want to update key-value-pair if needed. Just like object in Swift may would not update key-value-pair dictionary sometimes.
 */
- (NSDictionary *)toDictionary;


/**
 Create instance without any argument.

 @return Instance.
 */
+ (instancetype)model;

@end



@interface SPModelBase (Persistence)
/// 保存到本地（会覆盖之前保存的本类对象）
- (void)saveToDisk;
/// 从本地读取（仅能读取本类最后一次保存的对象）
+ (instancetype)loadFromDisk;
/// 从本地清除
+ (void)clearInDisk;
@end


@protocol ModelObserverDelegate;

@interface SPModelBase (Observation)
/// 让指定的属性被obj监听，当属性被赋予新值的时候会回调obj的协议方法:"observedObject:changeAtProperty:"。
- (void)observedBy:(id<ModelObserverDelegate>)obj atProperty:(NSString *)property;
/// 移除所有被obj监听的属性。
- (void)removeObservedBy:(id<ModelObserverDelegate>)obj;
/// 移除被obj监听的指定的属性。
- (void)removeObservedBy:(id<ModelObserverDelegate>)obj atProperty:(NSString *)property;
@end



@protocol ModelObserverDelegate<NSObject>
@required
/**
 * obj 属性发生变化的对象。
 * property 发生变化的属性。
 */
- (void)observedObject:(id)obj changeAtProperty:(NSString *)property;
@end

NS_ASSUME_NONNULL_END

#endif

